package com.scpii.json;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Wrapper for JSONWriter with some utility methods.
 */
public class JSONUtil {
	final static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

	/**
	 * Serializes an object into JSON.
	 * 
	 * @param object
	 *            to be serialized
	 * @return JSON string
	 * @throws JSONException
	 */
	public static String serialize(Object object) throws JSONException {
		JSONWriter writer = new JSONWriter();

		return writer.write(object);
	}

	/**
	 * Serializes an object into JSON, excluding any properties matching any of
	 * the regular expressions in the given collection.
	 * 
	 * @param object
	 *            to be serialized
	 * @param excludeProperties
	 *            Patterns matching properties to exclude
	 * @param ignoreHierarchy
	 *            whether to ignore properties defined on base classes of the
	 *            root object
	 * @return JSON string
	 * @throws JSONException
	 */
	public static String serialize(Object object,
			Collection<Pattern> excludeProperties,
			Collection<Pattern> includeProperties, boolean ignoreHierarchy,
			boolean excludeNullProperties) throws JSONException {
		JSONWriter writer = new JSONWriter();
		writer.setIgnoreHierarchy(ignoreHierarchy);
		return writer.write(object, excludeProperties, includeProperties,
				excludeNullProperties);
	}

	/**
	 * Serializes an object into JSON, excluding any properties matching any of
	 * the regular expressions in the given collection.
	 * 
	 * @param object
	 *            to be serialized
	 * @param excludeProperties
	 *            Patterns matching properties to exclude
	 * @param ignoreHierarchy
	 *            whether to ignore properties defined on base classes of the
	 *            root object
	 * @param enumAsBean
	 *            whether to serialized enums a Bean or name=value pair
	 * @return JSON string
	 * @throws JSONException
	 */
	public static String serialize(Object object,
			Collection<Pattern> excludeProperties,
			Collection<Pattern> includeProperties, boolean ignoreHierarchy,
			boolean enumAsBean, boolean excludeNullProperties)
			throws JSONException {
		JSONWriter writer = new JSONWriter();
		writer.setIgnoreHierarchy(ignoreHierarchy);
		writer.setEnumAsBean(enumAsBean);
		return writer.write(object, excludeProperties, includeProperties,
				excludeNullProperties);
	}

	/**
	 * Serializes an object into JSON to the given writer.
	 * 
	 * @param writer
	 *            Writer to serialize the object to
	 * @param object
	 *            object to be serialized
	 * @throws IOException
	 * @throws JSONException
	 */
	public static void serialize(Writer writer, Object object)
			throws IOException, JSONException {
		writer.write(serialize(object));
	}

	/**
	 * Serializes an object into JSON to the given writer, excluding any
	 * properties matching any of the regular expressions in the given
	 * collection.
	 * 
	 * @param writer
	 *            Writer to serialize the object to
	 * @param object
	 *            object to be serialized
	 * @param excludeProperties
	 *            Patterns matching properties to ignore
	 * @throws IOException
	 * @throws JSONException
	 */
	public static void serialize(Writer writer, Object object,
			Collection<Pattern> excludeProperties,
			Collection<Pattern> includeProperties, boolean excludeNullProperties)
			throws IOException, JSONException {
		writer.write(serialize(object, excludeProperties, includeProperties,
				true, excludeNullProperties));
	}

	/**
	 * Deserializes a object from JSON
	 * 
	 * @param json
	 *            string in JSON
	 * @return desrialized object
	 * @throws JSONException
	 */
	public static Object deserialize(String json) throws JSONException {
		JSONReader reader = new JSONReader();
		return reader.read(json);
	}

	/**
	 * Deserializes a object from JSON
	 * 
	 * @param reader
	 *            Reader to read a JSON string from
	 * @return deserialized object
	 * @throws JSONException
	 *             when IOException happens
	 */
	public static Object deserialize(Reader reader) throws JSONException {
		// read content
		BufferedReader bufferReader = new BufferedReader(reader);
		String line = null;
		StringBuilder buffer = new StringBuilder();

		try {
			while ((line = bufferReader.readLine()) != null) {
				buffer.append(line);
			}
		} catch (IOException e) {
			throw new JSONException(e);
		}

		return deserialize(buffer.toString());
	}

	public static List<String> asList(String commaDelim) {
		if ((commaDelim == null) || (commaDelim.trim().length() == 0))
			return null;
		List<String> list = new ArrayList<String>();
		String[] split = commaDelim.split(",");
		for (int i = 0; i < split.length; i++) {
			String trimmed = split[i].trim();
			if (trimmed.length() > 0) {
				list.add(trimmed);
			}
		}
		return list;
	}

}
